package asia.yuanding.wechat.web.service.impl;

import asia.yuanding.wechat.system.constant.BusinessStatus;
import asia.yuanding.wechat.system.constant.SystemConstant;
import asia.yuanding.wechat.system.exception.BusinessException;
import asia.yuanding.wechat.system.util.EmailUtil;
import asia.yuanding.wechat.system.util.ThreadUser;
import asia.yuanding.wechat.web.entity.User;
import asia.yuanding.wechat.web.entity.UserContactApply;
import asia.yuanding.wechat.web.netty.handler.MessageHandlerUtil;
import asia.yuanding.wechat.web.netty.handler.impl.ChatMessageHandler;
import asia.yuanding.wechat.web.netty.manager.ChannelManager;
import asia.yuanding.wechat.web.netty.vo.Result;
import asia.yuanding.wechat.web.service.UserContactApplyService;
import asia.yuanding.wechat.web.service.UserService;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import asia.yuanding.wechat.web.entity.UserContact;
import asia.yuanding.wechat.web.service.UserContactService;
import asia.yuanding.wechat.web.mapper.UserContactMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author YuanDing
* @description 针对表【user_contact】的数据库操作Service实现
* @createDate 2025-07-26 19:38:19
*/
@Service
public class UserContactServiceImpl extends ServiceImpl<UserContactMapper, UserContact>
    implements UserContactService{

    @Resource
    private UserContactMapper userContactMapper;

    @Resource
    private UserContactApplyService userContactApplyService;

    @Resource
    private UserService userService;

    @Resource
    private EmailUtil emailUtil;

    @Resource
    private ChatMessageHandler chatMessageHandler;


    /**
     * 申请好友
     * @param apply
     */
    @Override
    @Transactional
    public void apply(UserContactApply apply) throws BusinessException {
        String applyId = ThreadUser.getUId();
        String targetId = apply.getTargetId();

        // 不能申请自己为好友
        if (Objects.equals(applyId, targetId)) {
            throw new BusinessException("不能申请自己为好友");
        }

        // 如果被申请人已对申请人发起请求则驳回
        UserContactApply one = userContactApplyService.lambdaQuery()
                .eq(UserContactApply::getApplyId, targetId)
                .eq(UserContactApply::getTargetId, applyId)
                .eq(UserContactApply::getStatus, SystemConstant.UserApplyStatus.NOT_APPLY)
                .orderByDesc(UserContactApply::getCreateTime)
                .one();

        if (one != null) {
            throw new BusinessException("对方已发起联系人申请，请处理此联系人申请");
        }

        // 检查申请人对目标用户的关系状态
        UserContact applyUserContact = this.lambdaQuery()
                .eq(UserContact::getUserId, applyId)
                .eq(UserContact::getContactId, targetId)
                .orderByDesc(UserContact::getCreateTime)
                .one();




        if (applyUserContact != null) {
            // 已经是好友
            if (Objects.equals(applyUserContact.getStatus(), SystemConstant.UserContactStatus.FRIEND)) {
                throw new BusinessException("对方已经添加为好友");
            }
            // 被对方拉黑
            if (Objects.equals(applyUserContact.getStatus(), SystemConstant.UserContactStatus.BLOCKED)) {
                throw new BusinessException(BusinessStatus.BLOCKED.getCode(), BusinessStatus.BLOCKED.getMessage());
            }
            // 正在申请中
            if (Objects.equals(applyUserContact.getStatus(), SystemConstant.UserContactStatus.APPLYING)) {
                throw new BusinessException(BusinessStatus.APPLYING.getCode(), BusinessStatus.APPLYING.getMessage());
            }
        }

        // 检查目标用户对申请人的关系状态（防止被对方拉黑）
        UserContact targetUserContact = this.lambdaQuery()
                .eq(UserContact::getUserId, targetId)
                .eq(UserContact::getContactId, applyId)
                .one();

        if (targetUserContact != null) {
            // 被对方拉黑了
            if (Objects.equals(targetUserContact.getStatus(), SystemConstant.UserContactStatus.BLOCK)) {
                throw new BusinessException(BusinessStatus.BLOCKED.getCode(), BusinessStatus.BLOCKED.getMessage());
            }
        }

        // 检查是否有待处理的申请
        UserContactApply existingApply = userContactApplyService.lambdaQuery()
                .eq(UserContactApply::getApplyId, applyId)
                .eq(UserContactApply::getTargetId, targetId)
                .eq(UserContactApply::getStatus, SystemConstant.UserApplyStatus.NOT_APPLY)
                .one();

        if (existingApply != null) {
            throw new BusinessException(BusinessStatus.APPLYING.getCode(), BusinessStatus.APPLYING.getMessage());
        }

        // 设置申请信息
        apply.setApplyId(applyId);
        apply.setStatus(SystemConstant.UserApplyStatus.NOT_APPLY);
        apply.setCreateTime(new Date());

        // 保存申请记录
        boolean save = userContactApplyService.save(apply);
        if (save) {
            // 判断一下目标用户是否在线，不在线发邮件 在线直接推送
            if (ChannelManager.getChannel(targetId) != null) {
                ChannelManager.getChannel(targetId).writeAndFlush(MessageHandlerUtil.getResult(Result.ok("contactApply" , apply)));
            } else {
                emailUtil.sendContactApply(applyId , targetId);
            }


        }
    }

    /**
     * 获取好友申请列表
     * @param uid
     * @return
     */
    @Override
    public List<UserContactApply> getApplyList(String uid) {
        // 获取关于自己的所有申请记录
        List<UserContactApply> allApplies = userContactApplyService.lambdaQuery()
                .eq(UserContactApply::getTargetId, uid)
                .or()
                .eq(UserContactApply::getApplyId, uid)
                .orderByDesc(UserContactApply::getCreateTime)
                .list();

        if (allApplies.isEmpty()) {
            return Collections.emptyList();
        }

        // 按照申请人和被申请人的组合去重，只保留最新的一条记录
        Map<String, UserContactApply> latestAppliesMap = new HashMap<>();
        
        for (UserContactApply apply : allApplies) {
            // 生成唯一键：申请人_被申请人
            String key = apply.getApplyId() + "_" + apply.getTargetId();
            
            // 如果还没有这个组合的记录，或者当前记录更新，则保存
            if (!latestAppliesMap.containsKey(key)) {
                latestAppliesMap.put(key, apply);
            }
        }

        List<UserContactApply> userContactApplies = new ArrayList<>(latestAppliesMap.values());

        if (!userContactApplies.isEmpty()) {
            // 用户申请的好友uid列表（我申请别人的）
            List<String> myApplyTargetIds = userContactApplies.stream()
                    .filter(item -> item.getApplyId().equals(uid))
                    .map(UserContactApply::getTargetId)
                    .collect(Collectors.toList());

            if (!myApplyTargetIds.isEmpty()) {
                // 查询用户详情
                Map<String, User> userMap = userService.lambdaQuery()
                        .in(User::getUid, myApplyTargetIds)
                        .list()
                        .stream()
                        .collect(Collectors.toMap(User::getUid, item -> item));

                // 回填用户详情
                userContactApplies.stream()
                        .filter(item -> item.getApplyId().equals(uid))
                        .forEach(item -> item.setUserInfo(userMap.get(item.getTargetId())));
            }

            // 用户被申请的好友uid列表（别人申请我的）
            List<String> othersApplyIds = userContactApplies.stream()
                    .filter(item -> item.getTargetId().equals(uid))
                    .map(UserContactApply::getApplyId)
                    .collect(Collectors.toList());

            if (!othersApplyIds.isEmpty()) {
                // 查询用户详情
                Map<String, User> userMap2 = userService.lambdaQuery()
                        .in(User::getUid, othersApplyIds)
                        .list()
                        .stream()
                        .collect(Collectors.toMap(User::getUid, item -> item));

                // 回填用户详情
                userContactApplies.stream()
                        .filter(item -> item.getTargetId().equals(uid))
                        .forEach(item -> item.setUserInfo(userMap2.get(item.getApplyId())));
            }

            // 按创建时间倒序排列
            userContactApplies.sort((a, b) -> b.getCreateTime().compareTo(a.getCreateTime()));
            
            return userContactApplies;
        }
        
        return Collections.emptyList();
    }

    /**
     * 处理好友申请
     * @param apply
     */
    @Override
    @Transactional
    public void handleApply(UserContactApply apply) throws BusinessException {
        String currentUserId = ThreadUser.getUId();
        
        // 查找申请记录
        UserContactApply userContactApply = userContactApplyService.getOne(new LambdaQueryWrapper<UserContactApply>()
                .eq(UserContactApply::getTargetId, currentUserId)
                .eq(UserContactApply::getApplyId, apply.getApplyId())
                .eq(UserContactApply::getStatus, SystemConstant.UserApplyStatus.NOT_APPLY));

        if (userContactApply == null) {
            throw new BusinessException("申请记录不存在或已处理");
        }

        // 更新申请状态
        apply.setId(userContactApply.getId());
        boolean result = userContactApplyService.updateById(apply);

        if (result && Objects.equals(apply.getStatus(), SystemConstant.UserApplyStatus.APPLY)) {
            String contactRemark = "";

            // 同意申请，创建或更新双向好友关系
            String targetId = userContactApply.getTargetId(); // 被申请人（当前用户）
            String applyId = userContactApply.getApplyId();   // 申请人

            // 处理申请人的好友记录
            UserContact existingApplyUserContact = this.lambdaQuery()
                    .eq(UserContact::getUserId, applyId)
                    .eq(UserContact::getContactId, targetId)
                    .one();

            if (existingApplyUserContact != null) {
                // 更新现有记录
                existingApplyUserContact.setContactRemark(userContactApply.getRemark());
                existingApplyUserContact.setStatus(SystemConstant.UserContactStatus.FRIEND);
                existingApplyUserContact.setFriendPermission(userContactApply.getFriendPermission());
                contactRemark = existingApplyUserContact.getContactRemark();
                this.updateById(existingApplyUserContact);
            } else {
                // 创建新记录
                UserContact applyUserContact = new UserContact();
                applyUserContact.setContactRemark(userContactApply.getRemark());
                applyUserContact.setUserId(applyId);
                applyUserContact.setContactId(targetId);
                applyUserContact.setType(SystemConstant.UserContactType.USER);
                applyUserContact.setStatus(SystemConstant.UserContactStatus.FRIEND);
                applyUserContact.setFriendPermission(userContactApply.getFriendPermission());
                applyUserContact.setCreateTime(new Date());
                contactRemark = applyUserContact.getContactRemark();
                this.save(applyUserContact);
            }

            // 处理被申请人的好友记录
            UserContact existingTargetUserContact = this.lambdaQuery()
                    .eq(UserContact::getUserId, targetId)
                    .eq(UserContact::getContactId, applyId)
                    .one();

            if (existingTargetUserContact != null) {
                // 更新现有记录
                existingTargetUserContact.setStatus(SystemConstant.UserContactStatus.FRIEND);
                existingTargetUserContact.setFriendPermission(userContactApply.getFriendPermission());
                
                // 设置备注
                if (StrUtil.isNotBlank(apply.getRemark())) {
                    existingTargetUserContact.setContactRemark(apply.getRemark());
                } else if (StrUtil.isBlank(existingTargetUserContact.getContactRemark())) {
                    // 如果没有备注且原来也没有备注，则设置为申请人昵称
                    User applyUser = userService.lambdaQuery()
                            .eq(User::getUid, applyId).one();
                    if (applyUser != null) {
                        existingTargetUserContact.setContactRemark(applyUser.getNickname());
                    }
                }
                
                this.updateById(existingTargetUserContact);
            } else {
                // 创建新记录
                UserContact targetUserContact = new UserContact();
                targetUserContact.setUserId(targetId);
                targetUserContact.setContactId(applyId);
                targetUserContact.setType(SystemConstant.UserContactType.USER);
                targetUserContact.setStatus(SystemConstant.UserContactStatus.FRIEND);
                targetUserContact.setFriendPermission(userContactApply.getFriendPermission());
                targetUserContact.setCreateTime(new Date());
                
                // 设置备注
                if (StrUtil.isNotBlank(apply.getRemark())) {
                    targetUserContact.setContactRemark(apply.getRemark());
                } else {
                    // 默认备注为申请人的昵称
                    User applyUser = userService.lambdaQuery()
                            .eq(User::getUid, applyId).one();
                    if (applyUser != null) {
                        targetUserContact.setContactRemark(applyUser.getNickname());
                    }
                }

                
                this.save(targetUserContact);
            }

            emailUtil.sendHandleApplyNotice(applyId , contactRemark);
        }
    }

    @Override
    public List<UserContact> getUserFriendList(String uid) {

        List<UserContact> userContactList = this.lambdaQuery()
                .eq(UserContact::getUserId, uid)
                .eq(UserContact::getStatus, SystemConstant.UserContactStatus.FRIEND)
                .list();

        if (!userContactList.isEmpty()) {
            List<String> uIdList = userContactList.stream().map(UserContact::getContactId).distinct()
                    .collect(Collectors.toList());

            Map<String, User> userMap = userService.lambdaQuery()
                    .in(User::getUid, uIdList)
                    .list()
                    .stream()
                    .collect(Collectors.toMap(User::getUid, item -> item));

            userContactList.forEach(item -> {
                item.setUserInfo(userMap.get(item.getContactId()));
            });

            return userContactList;

        }

        return Collections.emptyList();
    }

    /**
     * 删除好友
     * @param contactId 要删除的好友ID
     */
    @Override
    @Transactional
    public void deleteFriend(String contactId) throws BusinessException {
        String currentUserId = ThreadUser.getUId();

        // 不能删除自己
        if (Objects.equals(currentUserId, contactId)) {
            throw new BusinessException("不能删除自己");
        }

        // 查找当前用户对目标用户的好友记录
        UserContact userContact = this.lambdaQuery()
                .eq(UserContact::getUserId, currentUserId)
                .eq(UserContact::getContactId, contactId)
                .one();

        if (userContact == null) {
            throw new BusinessException("好友关系不存在");
        }

        // 检查是否已经是好友状态
        if (!Objects.equals(userContact.getStatus(), SystemConstant.UserContactStatus.FRIEND)) {
            throw new BusinessException("对方不是你的好友");
        }

        // 更新当前用户对目标用户的状态为已删除
        userContact.setStatus(SystemConstant.UserContactStatus.DEL);
        this.updateById(userContact);

        // 查找目标用户对当前用户的好友记录
        UserContact targetUserContact = this.lambdaQuery()
                .eq(UserContact::getUserId, contactId)
                .eq(UserContact::getContactId, currentUserId)
                .one();

        if (targetUserContact != null) {
            // 更新目标用户对当前用户的状态为被好友删除
            targetUserContact.setStatus(SystemConstant.UserContactStatus.DELETED);
            this.updateById(targetUserContact);
        }
    }


}




